from typing import Union

from sqlalchemy import insert, select, update

from forward.api.admin.schemas.system import SystemConfigSchema
from forward.dependencies.database import db
from forward.model.tables import SystemConfigModel
from .tools import ToolsUtil

__all__ = ["ConfigUtil"]


class ConfigUtil:
    """数据库配置操作工具"""

    @staticmethod
    async def get(type_: str, name: str | None = None) -> dict:
        """根据类型和名称获取配置字典"""
        where = [SystemConfigModel.type == type_]
        if name:
            where.append(SystemConfigModel.name == name)
        configs = [
            SystemConfigSchema.model_validate(i, from_attributes=True)
            for i in await db.fetch_all(select(SystemConfigModel).where(*where))
        ]
        return {i.name: i.value for i in configs}

    @staticmethod
    async def get_val(type_: str, name: str, default: str | None = None) -> str | None:
        """根据类型和名称获取配置值"""
        config = await ConfigUtil.get(type_, name)
        if name not in config:
            return default
        return config.get(name)

    @staticmethod
    async def get_map(type_: str, name: str) -> Union[dict, None]:
        """根据类型和名称获取配置值(Json字符串转dict)"""
        value = await ConfigUtil.get_val(type_, name)
        if value is None:
            return None
        if not value:
            return {}
        return ToolsUtil.json_to_map(value)

    @staticmethod
    async def set(type_: str, name: str, val: str):
        """设置配置的值"""
        config_record = await db.fetch_one(
            select(SystemConfigModel).where(
                SystemConfigModel.type == type_, SystemConfigModel.name == name
            )
        )
        if config_record:
            config = SystemConfigSchema.model_validate(
                config_record, from_attributes=True
            )
            await db.execute(
                update(SystemConfigModel)
                .where(SystemConfigModel.id == config.id)
                .values(value=val)
            )
        else:
            await db.execute(
                insert(SystemConfigModel).values(type=type_, name=name, value=val)
            )
